iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 20
1
Software Development

動態規劃百題之經典、理論與實作系列 第 20

Day 20: 今天沒什麼論數只好重新檢視數論的問題吧!

  • 分享至 

  • xImage
  •  

是的,今天仍是動態規劃系列。今天來討論哩扣上面跟整除有關的動態規劃問題吧~

Exercise 35: Leetcode 650 - 2 Keys Keyboard

題目連結

https://leetcode.com/problems/2-keys-keyboard/

題目敘述

一開始螢幕上有個 "A" 字元。你有兩個按鈕,每次可以「複製全部」或是「貼上前次複製的東西」。請問至少要按幾次按鈕才能夠湊齊 n 個字元呢?

解題思考

我們用 C 代表複製 P 代表貼上。那麼輸入序列一定可以被分成「複製+若干次貼上」的許多段落。考慮最後一段,貼上若干次以後湊齊 n 個字元。因此此次複製的東西一定是 n 的因數。所以呢,我們想要作的事情就是找出那個因數 d 使得 dp(n) = dp(d) + 1次複製 + (n/d-1) 次貼上。

這題時間複雜度比較精妙一些。其實我們只需要計算 n 的所有因數的狀態就行了,其實可以做到 n 的O(因數個數*質因數個數)時間。只是因為這題範圍實在太小,所以可以很輕鬆地考慮所有 n。

參考程式碼 (Python3)

class Solution:
    def minSteps(self, n: int) -> int:
        dp = [0] * (n+1)
        dp[1] = 0
        for k in range(2, n+1):
            dp[k] = k
            for i in range(2, k):
                if k % i == 0:
                    dp[k] = min(dp[k], dp[i] + (k//i))
        return dp[n]

Exercise 36: Leetcode 368 - Largest Divisible Subset

題目連結

https://leetcode.com/problems/largest-divisible-subset/

題目敘述

給你 n 個相異的數字。請找出最大的子集合,使得集合內任何兩個數字 Si, Sj 要嘛 Si % Sj == 0 要嘛 Sj % Si == 0。最後輸出這個子集合。

解題思考

根據集合條件,答案的集合內元素一定是從小到大一個整除下一個。因此我們可以作 LIS 類似的概念:先把所有數字由小到大排列好。然後對於每一個數字,找看看前面能夠整除它的數字中,最長的那串到底有多長就行了。

這題的範圍好像很小,我們可以輕易地把整串數字通通拷貝出來,時間複雜度應該會是個 n^3。但寫起來世界無敵短。而且 python 很好用。

參考程式碼 (Python3)

class Solution:
    def largestDivisibleSubset(self, nums: List[int]) -> List[int]:
        dp = [[x] for x in nums]
        nums.sort()
        for i in range(len(nums)):
            for j in range(0, i):
                if nums[i] % nums[j] == 0 and len(dp[i]) < len(dp[j]) + 1:
                    dp[i] = dp[j] + [nums[i]]
        return max(dp, key=len, default=[])

快要追上去年21天的紀錄了呢。希望今年可以成功寫完30天。好的我們明天見~


上一篇
Day 19: 從內而外更新的動態規劃總是令人讚嘆連連!
下一篇
Day 21: 記錄下每個字元前一次出現的地方很有幫助!
系列文
動態規劃百題之經典、理論與實作30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
polymath
iT邦新手 5 級 ‧ 2020-05-16 19:40:33

想請問Largest Divisible Subset為何時間複雜度不是n^2,
雙層迴圈之外還多了什麼呢?

卡卡恩 iT邦新手 4 級 ‧ 2020-05-17 02:13:01 檢舉

最裡面的 dp[i] 更新是整個 List 更新(這一步並非常數時間更新),可能這步會花到 n 的時間。

polymath iT邦新手 5 級 ‧ 2020-05-17 02:49:20 檢舉

原來如此,感謝

我要留言

立即登入留言